package com.yilin.commons.util;

import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * GCJ-02(火星坐标) 和 BD-09 （百度坐标）
 * 算法代码如下，其中 bd_encrypt 将 GCJ-02 坐标转换成 BD-09 坐标， bd_decrypt 反之。
 */

public class GpsMapUtil {

    private static final float EARTH_RADIUS = (float) 6378.137;  //地球半径(km)
    private static final double PI = 3.14159265; // π
    private static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;//百度转火星


    public static void main(String[] args) {
        double distance = getDistance("106.49,29.59", "106.769263,26.554463");
        System.out.println(distance);
    }

    //火星转百度 加密
    public static double[] bdEncrypt(double gg_lat, double gg_lon) {
        double z = Math.sqrt(gg_lon * gg_lon + gg_lat * gg_lat) + 0.00002 * Math.sin(gg_lat * x_pi);
        double theta = Math.atan2(gg_lat, gg_lon) + 0.000003 * Math.cos(gg_lon * x_pi);
        double bd_lon = z * Math.cos(theta) + 0.0065;
        double bd_lat = z * Math.sin(theta) + 0.006;
        System.out.println(bd_lon + "," + bd_lat);
        float lon = new BigDecimal(String.valueOf(bd_lon)).floatValue();
        float lat = new BigDecimal(String.valueOf(bd_lat)).floatValue();
        System.out.println(lon + "," + lat);
        return new double[]{lon, lat};
    }

    //百度转火星 解密
    public static double[] bdDecrypt(double bd_lat, double bd_lon) {
        double x = bd_lon - 0.0065, y = bd_lat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        double gg_lon = z * Math.cos(theta);
        double gg_lat = z * Math.sin(theta);
        return new double[]{gg_lon, gg_lat};
    }

    public static double getDistance() {
        return getDistance(0, 0, 0, 0);
    }

    public static double getDistance(String startLngLat, String endLngLat) {
        return getDistance(parseLatLng(startLngLat)[1], parseLatLng(startLngLat)[0], parseLatLng(endLngLat)[1], parseLatLng(endLngLat)[0]);
    }

    //根据经纬度计算距离
    public static double getDistance(double startLng, double startLat, double endLng, double endLat) {
        double lat1 = (Math.PI / 180) * startLat;
        double lng1 = (Math.PI / 180) * startLng;
        double lat2 = (Math.PI / 180) * endLat;
        double lng2 = (Math.PI / 180) * endLng;
        double d = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lng2 - lng1)) * EARTH_RADIUS;
        // 弧长乘地球半径, 返回单位: 千米
        return Math.abs(d);
    }

    /*
     * 根据相邻两点获取角度
     * 1 开始经纬度
     * 2 结束经纬度
     * */
    public static float bearing(float lat1, float lng1, float lat2, float lng2) {
        double dRotateAngle = Math.atan2(Math.abs(lng1 - lng2), Math.abs(lat1 - lat2));
        if (lng2 >= lng1) {
            if (lat2 < lat1) dRotateAngle = Math.PI - dRotateAngle;
        } else {
            if (lat2 >= lat1) dRotateAngle = 2 * Math.PI - dRotateAngle;
            else dRotateAngle = Math.PI + dRotateAngle;
        }
        dRotateAngle = dRotateAngle * 180 / Math.PI;
        return (float) dRotateAngle;

    }

    //计算经纬度取值范围
    private static double[] getAround() {
        double degree = (24901 * 1609) / 360.0;//或者等于2*PI*EARTH_RADIUS 》地球半径
        double dpmLat = 1 / degree;
        double radiusLat = dpmLat * (double) 2000;
        double minLat = 106.775496 - radiusLat;
        double maxLat = 106.775496 + radiusLat;
        double mpdLng = degree * Math.cos(106.775496 * (PI / 180));
        double dpmLng = 1 / mpdLng;
        double radiusLng = dpmLng * (double) 2000;
        double minLng = 26.560468 - radiusLng;
        double maxLng = 26.560468 + radiusLng;
        //System.out.println("["+minLat+","+minLng+","+maxLat+","+maxLng+"]");
        return new double[]{minLat, minLng, maxLat, maxLng};
    }

    /**
     * 根据经纬度获取地址信息
     */
    public static String getAddress(String longLat) {
        String result = "";
        try {
            // 把字符串转换为URL请求地址
            URL url = new URL("https://api.map.baidu.com/reverse_geocoding/v3/?ak=yC8qinD7yxH27GQixFvrhboAdxVfUoIO&" +
                    "output=json&coordtype=bd09ll&language=local&location=" + longLat);
            // 打开连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 连接会话
            connection.connect();
            // 获取输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            StringBuilder sb = new StringBuilder();
            // 循环读取流
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            br.close();// 关闭流
            connection.disconnect();// 断开连接
            result = sb.toString();
            //截取地址信息
            String lnt = StringUtils.substringBefore(result, "\",\"business\"");
            return StringUtils.substringAfter(lnt, "\"formatted_address\":\"");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    // 格式化坐标
    private static double[] parseLatLng(String value) {
        try {
            if (!value.contains(",")) return new double[]{0, 0};
            String[] split = value.split(",");
            return new double[]{Float.parseFloat(split[1]), Float.parseFloat(split[0])};
        } catch (Exception e) {
            return new double[]{0, 0};
        }
    }

//    // 坐标三元排序 发货点
//    public static List<TransitOrderNote> sortORLatLngList(List<TransitOrderNote> allPointList, String truckLngLat) {
//        if (truckLngLat==null) return allPointList;
//        return ArrayUtil.sortPoTList(truckLngLat, allPointList, new ArrayList<>(), (p, a, b) -> {
//            double v = GpsMapUtil.getDistance(p, a.getConsignorCoordinate()) - GpsMapUtil.getDistance(p, b.getConsignorCoordinate());
//            return v > 0 ? 1 : (v < 0 ? -1 : 0);
//        }, TransitOrderNote::getConsignorCoordinate);
//    }
//
//    // 坐标三元排序 收货点
//    public static List<TransitOrderNote> sortEELatLngList(List<TransitOrderNote> allPointList, String truckLngLat) {
//        if (truckLngLat==null) return allPointList;
//        return ArrayUtil.sortPoTList(truckLngLat, allPointList, new ArrayList<>(), (p, a, b) -> {
//            double v = GpsMapUtil.getDistance(p, a.getConsigneeCoordinate()) - GpsMapUtil.getDistance(p, b.getConsigneeCoordinate());
//            return v > 0 ? 1 : (v < 0 ? -1 : 0);
//        }, TransitOrderNote::getConsigneeCoordinate);
//    }
}

